/* uart.c
* Copyright (C) 2006  Benedikt Sauter
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>

#include "uart.h"

/**
 * Init function for USART0
 **/
void UARTInit (void)
{
	/* U2X=0 (normal speed)
	 * */
	// F_OSC = 16 Mhz, divider = 25, Baudrate = 38400 Baud
	UBRR0H = 0;	// 4 most  significant bits of 25 = 0b0000  =  0
	UBRR0L = 25;	// 8 least significant bits       = 0b11001 = 25
//UCSR0A |= (1 << U2X);

	/* Enable receiver and transmitter and Receive interupt */
	//UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
	UCSR0B = (1 << RXEN0) | (1 << TXEN0);

	/* Set frame format: 8data, 1stop bit 8N1
	 * 0 << USBS0 = 1 stop bit
	 * 1 << USBS0 = 2 stop bits (p.193)
	 *
	 * 3 << UCSZ00 = 8 data bits (p.193)
	 * */
	UCSR0C = (0 << USBS0) | (3 << UCSZ00);
}

//void UARTInitDynamic (int baud, char flags)
//{
//}

/**
 * Sends one char through USART0
 * \param char - the char to be send
 */
void UARTPutChar (char data)
{
	/* Wait for empty transmit buffer */
	while (!(UCSR0A & (1 << UDRE0))) ;
	/* Put data into buffer, sends the data */
	UDR0 = data;
}

uint8_t UARTGetChar (void)
{
	while (!(UCSR0A & (1 << RXC0))) ;	// warten bis Zeichen verfuegbar
	return UDR0;
}

void UARTWrite (const char *msg)
{
	while (*msg != '\0')
		UARTPutChar (*msg++);
}

void UARTWrite_P (const char *msg)
{
#if defined(MT_BOOTLOADER_ADDRESS) && (MT_BOOTLOADER_ADDRESS > 0xFFFF)
	// when working in memory beyond pgm=0x7FFF (= 0xFFFF as 8bit addr)
	// http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=34344&start=0
	char c;
	uint32_t f = 0x10000UL + (uint32_t) (uint16_t) msg;
	while ((c = pgm_read_byte_far(f++)) != 0)
		UARTPutChar (c);
#else
	char c;
	while ((c = pgm_read_byte(msg++)) != 0)
		UARTPutChar (c);
#endif
}

// not used ...
//uint8_t AsciiToHex (uint8_t high, uint8_t low)
//{
//	// check if lower equal 9 ( ascii 57 )
//	if (high <= 57)				// high is a number
//		high = high - 48;
//	else						// high is a letter
//		high = high - 87;
//
//	// check if lower equal 9 ( ascii 57 )
//	if (low <= 57)				// high is a number
//		low = low - 48;
//	else						// high is a letter
//		low = low - 87;
//
//	return (high << 4) | low;
//}

void SendHex (uint8_t hex)
{
	uint8_t nibble;

	nibble = hex >> 4;
	if (nibble <= 9)
		UARTPutChar (nibble + 48);
	else
		UARTPutChar (nibble + 87);

	nibble  = hex & 0x0F;
	if (nibble <= 9)
		UARTPutChar (nibble + 48);
	else
		UARTPutChar (nibble + 87);
}
